#ifndef __AIP_VOICE_H__
#define __AIP_VOICE_H__

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <alsa/asoundlib.h>

namespace aip {
    class Voice{
    public:

        static const int channels = 1; // 声道数：立体声
        unsigned int sample_rate = 16000; // 采样率     
        const char* PCM_DEVICE = "default"; // 默认的PCM设备
        snd_pcm_uframes_t frames = 1024; // 每次读取或写入的帧数
        //std::string filename = "recorded_audio.pcm";

        void get_voice(int duration_seconds, std::string filename){
            snd_pcm_t *pcm_handle; // PCM设备句柄
            snd_pcm_hw_params_t *params; // 硬件参数对象
            char *buffer; // 音频数据缓冲区

            // Step 1: 打开PCM设备用于录音（捕获）
            int rc = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_CAPTURE, 0);
            if (rc < 0) {
                std::cerr << "无法打开PCM设备: " << snd_strerror(rc) << std::endl;
                return;
            }

            // 分配参数对象并填充默认值
            snd_pcm_hw_params_alloca(&params);
            snd_pcm_hw_params_any(pcm_handle, params);

            // 设置参数
            snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); // 设置访问模式为交错模式
            snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); // 设置采样格式为16位小端
            snd_pcm_hw_params_set_channels(pcm_handle, params, channels); // 设置声道数
            snd_pcm_hw_params_set_rate_near(pcm_handle, params, &sample_rate, 0); // 设置采样率
            snd_pcm_hw_params_set_period_size_near(pcm_handle, params, &frames, 0); // 设置每帧的样本数

            // 应用参数
            rc = snd_pcm_hw_params(pcm_handle, params);
            if (rc < 0) {
                std::cerr << "无法设置硬件参数: " << snd_strerror(rc) << std::endl;
                return;
            }

            // 分配缓冲区
            buffer = new char[frames * channels * 2]; // 每个样本2字节（16位）

            // Step 2: 录制音频并保存到文件
            record_audio(pcm_handle, frames, buffer, duration_seconds, filename.c_str());

            // Step 3: 关闭PCM设备（录音）
            snd_pcm_close(pcm_handle);

            // Step 4: 释放缓冲区
            delete[] buffer;
        }      

    private:

        // 录制音频的函数
        void record_audio(snd_pcm_t *pcm_handle, snd_pcm_uframes_t frames, char *buffer, int duration_seconds, const char *filename) {
            int rc;
            int total_frames = duration_seconds * sample_rate * channels; // 总帧数 = 采样率 * 时间 * 声道数
            int frames_recorded = 0;
            std::ofstream output_file(filename, std::ios::binary); // 打开文件用于写入二进制数据

            if (!output_file) {
                std::cerr << "无法打开文件 " << filename << " 用于写入！" << std::endl;
                return;
            }

            //std::cout << "开始录制，时长 " << duration_seconds << " 秒..." << std::endl;

            while (frames_recorded < total_frames) {
                rc = snd_pcm_readi(pcm_handle, buffer, frames); // 从PCM设备读取音频数据
                if (rc == -EPIPE) {
                    std::cerr << "发生溢出（Overrun）" << std::endl;
                    snd_pcm_prepare(pcm_handle); // 重新准备PCM设备
                } else if (rc < 0) {
                    std::cerr << "读取错误: " << snd_strerror(rc) << std::endl;
                } else {
                    frames_recorded += rc; // 累加已录制的帧数
                    // 将录制的音频数据写入文件
                    output_file.write(buffer, rc * channels * 2); // 每个样本2字节（16位）
                }
            }

            output_file.close(); // 关闭文件
            //std::cout << "录制完成！音频已保存到 " << filename << std::endl;
        }
        

    };
}

#endif